// ADDITIVE WAVETABLE SYNTHESIS
// D. TAYLOR 2014

typedef int16_t samp16bit;
typedef int32_t samp32bit;

// Wavetable interpolation method
#if WAVE_HQ_INTERPOLATE
#define WAVE_INTERPOLATE(A0, A1, A2, A3, R) (scubic((A0) << 14, (A1) << 15, (A2) << 15, (A3) << 14, R >> 1) << 4) // Cubic interpolation, 24bit result
#else
#define WAVE_INTERPOLATE(A0, A1, A2, A3, R) linear((A1) << 16, (A2) << 16, R) // Linear interpolation, 32bit result
#endif

// Readability macros
#define WAVE_SIZE  (1 << WAVE_BITS)         // Wavetable size

// LUT for MIP-mapped wavetable
static samp16bit wavetable[2 << (WAVE_BITS)];

// Wavetable MIP-level calculation
__inline
static uint32_t wave_calc_mip(uint32_t rate) {
  uint32_t mip = clz(rate);
  if(mip < 2) mip = 2;
  return mip > WAVE_BITS ? WAVE_BITS : mip;
}

// Wavetable MIP-level mu calculation
__inline
static uint32_t wave_calc_mu(uint32_t rate) {
  uint32_t mip = clz(rate);
  if(mip <= 2 || mip > WAVE_BITS) return 0;
  return rate << (mip + 1);
}

// Sample wave table (with MIP-mapping)
__inline
static samp32bit wave(uint32_t pos, uint32_t mip) {
  uint32_t register base = 1 << mip;
  uint32_t register index = pos >> (32 - mip);
  return wavetable[base + index] << 16;
}

// Sample wave table (with interpolation and MIP-mapping)
__inline
static samp32bit fwave(uint32_t pos, uint32_t mip) {
  uint32_t register base = 1 << mip;
  uint32_t register index = pos >> (32 - mip);
  if(mip <= 2) return -(fastsin(pos) >> 1); // use sine for > nyquist
  return WAVE_INTERPOLATE(
    wavetable[base + ((index - 1) & (base - 1))],
    wavetable[base + index],
    wavetable[base + ((index + 1) & (base - 1))],
    wavetable[base + ((index + 2) & (base - 1))],
    pos << mip
  );
}

// Sample wave table (with interpolation and interpolated MIP-mapping)
static samp32bit fmwave(uint32_t pos, uint32_t mip, uint32_t mu) {
  samp32bit sample = fwave(pos, mip);
  if(mip <= 2) return sample;
  return linear(sample, fwave(pos, mip - 1), mu);
}

// Auto-generate MIP-maps by decimation
void build_mipmaps() {
//  unsigned n;
/*  for(n = WAVE_BITS - 1; n > 1; n--)
    halfband(&wavetable[1 << n], &wavetable[2 << n], 1 << n);
	*/
}
